using System.Text.Json.Serialization;
using Microsoft.Extensions.DependencyInjection;

namespace Terra.Core.Common.ApiResponse;

using Terra.Core.Common.ErrorCodes.Models;
using Terra.Core.Common.ErrorCodes.Providers;

/// <summary>
/// 统一API响应格式
/// </summary>
/// <typeparam name="T">响应数据类型</typeparam>
public class ApiResponse<T>
{
    /// <summary>
    /// 错误码提供者
    /// </summary>
    protected static IErrorCodeProvider _errorCodeProvider;

    /// <summary>
    /// 初始化错误码提供者
    /// </summary>
    /// <param name="provider">错误码提供者</param>
    public static void Initialize(IErrorCodeProvider provider)
    {
        _errorCodeProvider = provider;
    }

    static ApiResponse()
    {
        // 默认使用 DefaultErrorCodeProvider
        _errorCodeProvider = new DefaultErrorCodeProvider();
    }

    /// <summary>
    /// 错误码
    /// </summary>
    [JsonPropertyName("code")]
    public string Code { get; set; }

    /// <summary>
    /// 错误消息
    /// </summary>
    [JsonPropertyName("message")]
    public string Message { get; set; }

    /// <summary>
    /// 数据
    /// </summary>
    [JsonPropertyName("data")]
    public T Data { get; set; }

    /// <summary>
    /// 是否成功
    /// </summary>
    [JsonPropertyName("success")]
    public bool IsSuccess { get; set; }

    /// <summary>
    /// 时间戳(毫秒)
    /// </summary>
    [JsonPropertyName("timestamp")]
    public long Timestamp { get; set; }

    /// <summary>
    /// 跟踪ID
    /// </summary>
    [JsonPropertyName("traceId")]
    public string TraceId { get; set; }

    /// <summary>
    /// 错误级别
    /// </summary>
    [JsonPropertyName("severity")]
    public ErrorSeverity Severity { get; set; }

    public ApiResponse()
    {
        Timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
        Severity = ErrorSeverity.Error;
    }

    public ApiResponse(string code, string message, T data, bool isSuccess = false)
    {
        Code = code;
        Message = message;
        Data = data;
        IsSuccess = isSuccess;
        Timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
        Severity = ErrorSeverity.Error;
    }

    /// <summary>
    /// 成功
    /// </summary>
    /// <param name="data">数据</param>
    /// <param name="message">消息</param>
    /// <returns></returns>
    public static ApiResponse<T> Success(T data, string message = "成功")
    {
        return new ApiResponse<T>
        {
            Code = ApiResponseCode.SUCCESS,
            Message = message,
            Data = data,
            IsSuccess = true,
            TraceId = string.Empty,
            Timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
            Severity = ErrorSeverity.Info
        };
    }

    /// <summary>
    /// 失败
    /// </summary>
    /// <param name="code">错误码</param>
    /// <param name="message">错误消息</param>
    /// <param name="severity">错误级别</param>
    /// <returns></returns>
    public static ApiResponse<T> Error(string code, string message, ErrorSeverity severity = ErrorSeverity.Error)
    {
        return new ApiResponse<T>
        {
            Code = code,
            Message = message,
            Data = default,
            IsSuccess = false,
            TraceId = string.Empty,
            Timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
            Severity = severity
        };
    }

    /// <summary>
    /// 失败（使用错误码）
    /// </summary>
    /// <param name="code">错误码</param>
    /// <returns></returns>
    public static ApiResponse<T> Error(string code)
    {
        var errorInfo = _errorCodeProvider.GetErrorInfo(code);
        return new ApiResponse<T>
        {
            Code = code,
            Message = errorInfo.Message,
            Data = default,
            IsSuccess = false,
            TraceId = string.Empty,
            Timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
            Severity = errorInfo.Severity
        };
    }

    /// <summary>
    /// 失败（使用错误码和格式化参数）
    /// </summary>
    /// <param name="code">错误码</param>
    /// <param name="args">格式化参数</param>
    /// <returns></returns>
    public static ApiResponse<T> Error(string code, params object[] args)
    {
        var errorInfo = _errorCodeProvider.GetErrorInfo(code);
        return new ApiResponse<T>
        {
            Code = code,
            Message = string.Format(errorInfo.Message, args),
            Data = default,
            IsSuccess = false,
            TraceId = string.Empty,
            Timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
            Severity = errorInfo.Severity
        };
    }
}

/// <summary>
/// 统一API响应格式(无数据)
/// </summary>
public class ApiResponse : ApiResponse<object>
{
    public ApiResponse() : base() { }

    public ApiResponse(string code, string message, object data, bool isSuccess = false)
        : base(code, message, data, isSuccess) { }

    /// <summary>
    /// 成功
    /// </summary>
    /// <param name="message">消息</param>
    /// <returns></returns>
    public static ApiResponse Success(string message = "成功")
    {
        return new ApiResponse
        {
            Code = ApiResponseCode.SUCCESS,
            Message = message,
            Data = null,
            IsSuccess = true,
            TraceId = string.Empty,
            Timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
            Severity = ErrorSeverity.Info
        };
    }

    /// <summary>
    /// 失败
    /// </summary>
    /// <param name="code">错误码</param>
    /// <param name="message">错误消息</param>
    /// <param name="severity">错误级别</param>
    /// <returns></returns>
    public static new ApiResponse Error(string code, string message, ErrorSeverity severity = ErrorSeverity.Error)
    {
        return new ApiResponse
        {
            Code = code,
            Message = message,
            Data = null,
            IsSuccess = false,
            TraceId = string.Empty,
            Timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
            Severity = severity
        };
    }

    /// <summary>
    /// 失败（使用错误码）
    /// </summary>
    /// <param name="code">错误码</param>
    /// <returns></returns>
    public static new ApiResponse Error(string code)
    {
        var errorInfo = _errorCodeProvider.GetErrorInfo(code);
        return new ApiResponse
        {
            Code = code,
            Message = errorInfo.Message,
            Data = null,
            IsSuccess = false,
            TraceId = string.Empty,
            Timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
            Severity = errorInfo.Severity
        };
    }

    /// <summary>
    /// 失败（使用错误码和格式化参数）
    /// </summary>
    /// <param name="code">错误码</param>
    /// <param name="args">格式化参数</param>
    /// <returns></returns>
    public static new ApiResponse Error(string code, params object[] args)
    {
        var errorInfo = _errorCodeProvider.GetErrorInfo(code);
        return new ApiResponse
        {
            Code = code,
            Message = string.Format(errorInfo.Message, args),
            Data = null,
            IsSuccess = false,
            TraceId = string.Empty,
            Timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
            Severity = errorInfo.Severity
        };
    }
}